package com.thinkwide.data.security;


import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Random;

public class MFCorssDES {

    private SecretKey secretKey;// 密钥
    private IvParameterSpec iv;// 偏移量
    private Cipher decryptCipher;// 解密对象

    /*
     * strKey必须是8位长度的字符串，即64bit。
     */
    public MFCorssDES(String strKey) {
        try {
            // 指定算法产生解密对象
            decryptCipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); //选择模式和填充方式，与.NET对应
            // 由用户密钥产生系统密钥
            secretKey = SecretKeyFactory.getInstance("DES").generateSecret(new DESKeySpec(strKey.getBytes("UTF-8")));
            // 产生偏移量
            iv = new IvParameterSpec(strKey.getBytes("UTF-8"));
            // 加载解密对象
            decryptCipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        }
    }

    /**
     * 解密.net平台上C#加密过的字节数组
     *
     * @param arrB 待解密的字节数组
     * @return 解密后的字节数组
     * @throws IllegalBlockSizeException
     * @throws BadPaddingException
     */
    public byte[] decrypt(byte[] arrB) throws IllegalBlockSizeException, BadPaddingException {
        return decryptCipher.doFinal(arrB);
    }

    public static String PadLeft(int strLength, String str) {
        int strLen = str.length();

        if (strLen < strLength) {
            while (strLen < strLength) {
                StringBuffer sb = new StringBuffer();
                sb.append("0").append(str);//左补0
                str = sb.toString();
                strLen = str.length();
            }
        }
        return str;
    }


    public static String CttEncryptionEngine(String Src, String Key, Boolean Encrypt) {
        int KeyLen;
        int KeyPos;
        Integer offset;
        String dest;
        String Sou;
        int SrcPos;
        int SrcAsc;
        int TmpSrcAsc;
        int Range;
        Random instance = new Random();

        if (Key.length() == 0) {
            Key = "illustrious";
        }
        KeyLen = Key.length();
        KeyPos = -1;
        if (Encrypt) {
            offset = instance.nextInt(256);
            dest = Integer.toHexString(offset);
            dest = PadLeft(2, dest);
            dest = dest.toUpperCase();
            Sou = offset.toString();
            //Sou = dest + "  souce " + Sou; // + offset.ToString;
            for (int i = 0; i < Src.length(); i++) {
                SrcAsc = ((int) Src.charAt(i) + offset) % 255;
                if (KeyPos < KeyLen - 1) KeyPos++;
                else KeyPos = 0;
                SrcAsc = SrcAsc ^ (int) Src.charAt(KeyPos);
                dest = dest + PadLeft(2, Integer.toHexString(SrcAsc)).toUpperCase();
                offset = SrcAsc;
            }

        } else {
            dest = "";
            if (Src.length() == 0) return "";

            offset = Integer.parseInt(Src.substring(0, 2), 16);
            SrcPos = 2;
            while (SrcPos < Src.length()) {

                SrcAsc = Integer.parseInt(Src.substring(SrcPos, SrcPos + 2), 16);
                if (KeyPos < KeyLen - 1) KeyPos++;
                else KeyPos = 0;
                TmpSrcAsc = SrcAsc ^ (int) Key.charAt(KeyPos);
                if (TmpSrcAsc <= offset)
                    TmpSrcAsc = 255 + TmpSrcAsc - offset;
                else
                    TmpSrcAsc = TmpSrcAsc - offset;
                dest = dest + (char) TmpSrcAsc;
                offset = SrcAsc;
                SrcPos = SrcPos + 2;
            }
        }

        return dest;

    }
}

